# *-* coding: utf-8 *-*
#===============================================================================
# Koro Business Environment
# Copyright (C) 2008  Antonio Corroppoli
#
#This file is part of Koro BE.
# 
# Koro BE is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# Koro BE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Koro BE; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#===============================================================================

'''
Created on 20/ago/2011

@author: antstud
'''
import wx
from koro.core import exception
from koro.util import to_bool,to_string, validate_sconti
from koro.ui.wxgui.panels import BasePanel,TotaliManager,OpzioniPanelBase#,TablePanel
from koro.ui.wxgui.widgets import controls as co,dialogs
from koro.ui.wxgui.mellcfg import mDefaultBorder
from koro.ui.wxgui import images
from koro.modules import lookup
from koro.modules.documenti.canvas import DocumentoCanvas, PreventivoCanvas

ID_IVA_PICKER=wx.NewId()
ID_RIGA_NEW=wx.NewId()
ID_RIGA_DEL=wx.NewId()
ID_RIGA_ADD=wx.NewId()

ID_REG_FATT_FORN=wx.NewId()
EVT_DETTAGLIO_CHANGED=wx.PyEventBinder(wx.NewEventType(),1)

def _get_editor(doc):
        if doc.is_preventivo():
            return PreventivoEditor
        elif doc.is_fattura():
            return FatturaEditor
        elif doc.is_arrivo():
            return ArrivoMerceEditor
        elif doc.is_reg_fatt_forn():
            return RegFattFornEditor
        else:
            raise Exception('Documento non riconosciuto: {0}'.format(doc.tipo_documento))


#===============================================================================
# RigaDocumentoPanel
#===============================================================================
class RigaDocumentoPanel(wx.Panel):
    '''Panel contenente i campi per l'inserimento/modifica di una riga documento.'''
    def __init__(self,*args,**kwargs):
        self.intestatario=kwargs.pop('intestatario')
        self.codice_listino=kwargs.pop('codice_listino',None)
        wx.Panel.__init__(self,*args,**kwargs)
        self.numero=-1
        self.SetClientSize((400,350))
        boxsizer=wx.BoxSizer(wx.VERTICAL)
        boxsizer.AddSpacer(10)
        hsizer=wx.BoxSizer()
        self.ID_prodotto=co.LabelTextCtrl(self,size=(50,-1),label='ID',
                                          orientation=wx.VERTICAL,
                                          mstyle=co.mTE_READ_ONLY)
        hsizer.Add(self.ID_prodotto,0,wx.LEFT|wx.RIGHT,border=5)
        
        self.cod_prod_forn = co.LabelTextCtrl(self,size=(240,-1),
                                              label='Codice Prod.Forn.',
                                              orientation=wx.VERTICAL)
        hsizer.Add(self.cod_prod_forn,0,wx.LEFT|wx.RIGHT,border=5)
        
        boxsizer.Add(hsizer,0,wx.LEFT,10)
        
        boxsizer.AddSpacer(10)
        self.prodotto = co.LabelLookupCtrl(self,size=(300, -1),
                                           label='Prodotto',style=0,
                                           orientation=wx.VERTICAL,
                                           view='descrizione')
        self.prodotto.set_lookup_context(lookup.LOOKUP_PRODOTTI)
        self.prodotto.show_cancel_button()
        #self.prodotto.set_filter(self.fornitore)
        self.prodotto.bind(co.EVT_AFTER_LOOKUP,self.prodotto_changed_callback)
        self.prodotto.bind(co.KEVT_AFTER_LOOKUP_CANCEL,self._lookup_cancel_callback)
        boxsizer.Add(self.prodotto,0,wx.LEFT,border=15)
        
        #boxsizer.Add(hsizer,0,wx.LEFT,10)
        boxsizer.AddSpacer(10)
        hsizer=wx.BoxSizer()
        self.prezzo = co.KValutaCtrl(parent=self,size=(150,-1),label='Prezzo',orientation=wx.VERTICAL)
        hsizer.Add(self.prezzo,0,wx.LEFT|wx.RIGHT,border=5)
        
        #boxsizer.AddSpacer(10)
        #self.quantita = co.LabelTextCtrl(parent=self,size=(140,-1),label='Quantità',orientation=wx.VERTICAL)
        self.quantita=co.KQuantityCtrl(self,size=(140,-1),label='Quantità',orientation=wx.VERTICAL)
        self.quantita.value=1
        hsizer.Add(self.quantita,0,wx.LEFT|wx.RIGHT,border=5)
        
        boxsizer.Add(hsizer,0,wx.LEFT,10)
        
        boxsizer.AddSpacer(10)
        
        hsizer=wx.BoxSizer()
        self.sconti = co.LabelTextCtrl(parent=self,size=(150,-1),label='Sconti',orientation=wx.VERTICAL)
        self.sconti.set_value(self.intestatario.sconti)
        hsizer.Add(self.sconti,0,wx.LEFT|wx.RIGHT,border=5)
        
        self.aliquota = co.IvaCtrl(parent=self,orientation=wx.VERTICAL)
        if self.intestatario is not None:
            self.aliquota.set_value(self.intestatario.iva)
        hsizer.Add(self.aliquota,0,wx.LEFT|wx.RIGHT,border=5)
        
        boxsizer.Add(hsizer,0,wx.LEFT,10)
        boxsizer.AddSpacer(10)
        self.movimenta=wx.CheckBox(self,label='Movimenta Magazzino')
        boxsizer.Add(self.movimenta,0,wx.LEFT,10)
        #boxsizer.AddSpacer(10)
        #boxsizer.AddSpacer(10)
        self.SetSizer(boxsizer)
        self.Layout()
    
    def _validate_sconti(self):
        try:
            validate_sconti(self.sconti.get_value())
        except exception.KoroValidationError,inst:
            wx.GetApp().show_error(inst)
            self.sconti.clear()
    
    def _request_prezzo(self,prodotto):
        prezzo=None
        if self.intestatario.is_fornitore():
            prezzo=prodotto.get_prezzo_fornitore(self.intestatario)
        else:
            prezzo=prodotto.get_prezzo(self.codice_listino)
        return prezzo
    
    def _lookup_cancel_callback(self):
        self.ID_prodotto.clear()
        self.cod_prod_forn.clear()
        self.prezzo.clear()
    
    def _request_add_product(self):
        observer=wx.GetApp().get_observer()
        observer.set_context('PRODOTTI')
        descrizione=self.prodotto.get_string_value()
        fornitore=self.intestatario
        cod_prod_forn=self.cod_prod_forn.get_value()
        prezzo=self.prezzo.get_value()
        aliquota_iva=self.aliquota.get_selected_object()
        obj=observer.create_object(descrizione,
                                   fornitore,
                                   cod_prod_forn,
                                   prezzo,
                                   aliquota_iva)
        self.prodotto.set_value(obj)
        self.prodotto_changed_callback(obj)
    
    def before_close(self):
        '''Questo metodo viene chiamato quando viene cliccato il pulsante 'applica'
        nella toolbar del KoroDialog, prima di chiamare EndModal.'''
        self._validate_sconti()
        prodotto=self.prodotto.get_selected_object()
        movimenta=self.movimenta.GetValue()
        if prodotto is not None and self.intestatario.is_cliente():
            self._check_giacenza(prodotto)
        if prodotto is None and movimenta:
            msg = 'Per movimentare il magazzino occorre creare il prodotto.\n'
            question = 'Aggiungere il prodotto alla lista prodotti?'
            response = wx.GetApp().show_question(msg+question)
            if response == wx.ID_YES:
                self._request_add_product()
            else:
                self.movimenta.SetValue(False)
    
    def _check_giacenza(self, prodotto):
        if not prodotto.has_magazzino():
            return
        qta = self.quantita.get_value()
        giac=prodotto.get_giacenza()
        question = 'La quantità richiesta ({0}) supera quella in giacenza ({1}).\nContinuare comunque?'
        question = question.format(qta,giac)
        if int(qta) > int(giac):
            response = wx.GetApp().show_question(question)
            if response == wx.ID_NO:
                raise Exception()
        
    def prodotto_changed_callback(self,prodotto):
        self.ID_prodotto.set_value(prodotto.get_ID_fmt())
        self.cod_prod_forn.set_value(prodotto.get_codice_prod_forn(self.intestatario))
        prezzo=self._request_prezzo(prodotto)
        self.prezzo.set_value(prezzo)
        self.movimenta.SetValue(prodotto.has_magazzino())
        if self.intestatario.iva is None:
            self.aliquota.set_value(prodotto.aliquota_iva)
    
    def update_fields(self,riga):#riceve una riga
        self.numero=riga.numero
        self.ID_prodotto.set_value(riga.get_ID_prodotto_fmt())
        self.cod_prod_forn.set_value(riga.get_cod_prod_forn())
        self.prodotto.set_value(riga.prodotto)
        if riga.prodotto is None:
            self.prodotto.change_value(riga.descrizione_riga)
        self.prezzo.set_value(riga.prezzo)
        self.quantita.value=riga.quantita
        self.sconti.set_value(riga.sconti)
        self.aliquota.set_value(riga.iva_obj)
        self.movimenta.SetValue(riga.movimenta)
    
    def reset_fields(self):
        self.numero=-1
        self.ID_prodotto.clear()
        self.cod_prod_forn.clear()
        self.prezzo.clear()
        self.aliquota.clear()
        self.prodotto.clear()
        self.sconti.clear()
        self.quantita.set_value('1')
    
    def update_object(self,obj):#riceve un documento
        '''Chiede di aggiungere il fornitore al prodotto se non presente.'''
        prezzo=self.prezzo.get_value()
        aliquota=self.aliquota.get_selected_object()
        sconti=self.sconti.get_value()
        prodotto=self.prodotto.get_selected_object()
        descrizione=self.prodotto.get_string_value()
        cod_prod_forn=self.cod_prod_forn.get_value()
        quantita=self.quantita.value
        movimenta=self.movimenta.GetValue()
        try:
            obj.save_riga(numero=self.numero,
                      descrizione=descrizione,
                      prodotto=prodotto,
                      cod_prod_forn=cod_prod_forn,
                      prezzo=prezzo,
                      iva=aliquota,
                      sconti=sconti,
                      quantita=quantita,
                      movimenta=movimenta)
        except exception.KoroIncompleteObject,inst:
            response=wx.GetApp().show_question(inst.message+"\nAggiungere il fornitore al prodotto?")
            if response==wx.ID_YES:
                prodotto.add_info_fornitore(self.intestatario,
                                            cod_prod_forn,
                                            prezzo,
                                            False)


#===============================================================================
# RigaAcquistoPanel
#===============================================================================
class RigaAcquistoPanel(wx.Panel):
    '''Panel contenente i campi per l'inserimento/modifica di una riga documento.'''
    def __init__(self,*args,**kwargs):
        self.intestatario=kwargs.pop('intestatario')
        self.codice_listino=kwargs.pop('codice_listino',None)
        wx.Panel.__init__(self,*args,**kwargs)
        self.numero=-1
        self.SetClientSize((400,350))
        boxsizer=wx.BoxSizer(wx.VERTICAL)
        boxsizer.AddSpacer(10)
        hsizer=wx.BoxSizer()
        self.ID_prodotto=co.LabelTextCtrl(self,size=(50,-1),label='ID',
                                          orientation=wx.VERTICAL,
                                          mstyle=co.mTE_READ_ONLY)
        hsizer.Add(self.ID_prodotto,0,wx.LEFT|wx.RIGHT,border=5)
        
        self.cod_prod_forn = co.LabelTextCtrl(self,size=(240,-1),
                                              label='Codice Prod.Forn.',
                                              orientation=wx.VERTICAL)
        hsizer.Add(self.cod_prod_forn,0,wx.LEFT|wx.RIGHT,border=5)
        
        boxsizer.Add(hsizer,0,wx.LEFT,10)
        
        boxsizer.AddSpacer(10)
        self.prodotto = co.LabelLookupCtrl(self,size=(300, -1),
                                           label='Prodotto',style=wx.TE_PROCESS_ENTER,
                                           orientation=wx.VERTICAL,
                                           view='descrizione'
                                           )
        self.prodotto.set_lookup_context(lookup.LOOKUP_PRODOTTI, co.ACQUISTO)
        self.prodotto.show_cancel_button()
        #self.prodotto.set_filter(self.fornitore)
        self.prodotto.bind(co.EVT_AFTER_LOOKUP,self.prodotto_changed_callback)
        self.prodotto.bind(co.KEVT_AFTER_LOOKUP_CANCEL,self._lookup_cancel_callback)
        boxsizer.Add(self.prodotto,0,wx.LEFT,border=15)
        
        #boxsizer.Add(hsizer,0,wx.LEFT,10)
        boxsizer.AddSpacer(10)
        hsizer=wx.BoxSizer()
        self.prezzo = co.KValutaCtrl(parent=self,size=(150,-1),label='Prezzo',orientation=wx.VERTICAL)
        hsizer.Add(self.prezzo,0,wx.LEFT|wx.RIGHT,border=5)
        
        #boxsizer.AddSpacer(10)
        #self.quantita = co.LabelTextCtrl(parent=self,size=(140,-1),label='Quantità',orientation=wx.VERTICAL)
        self.quantita=co.KQuantityCtrl(self,size=(140,-1),label='Quantità',orientation=wx.VERTICAL)
        self.quantita.value=1
        hsizer.Add(self.quantita,0,wx.LEFT|wx.RIGHT,border=5)
        
        boxsizer.Add(hsizer,0,wx.LEFT,10)
        
        boxsizer.AddSpacer(10)
        
        hsizer=wx.BoxSizer()
        self.sconti = co.LabelTextCtrl(parent=self,size=(150,-1),label='Sconti',orientation=wx.VERTICAL)
        self.sconti.set_value(self.intestatario.sconti)
        hsizer.Add(self.sconti,0,wx.LEFT|wx.RIGHT,border=5)
        
        self.aliquota = co.IvaCtrl(parent=self,orientation=wx.VERTICAL)
        if self.intestatario is not None:
            self.aliquota.set_value(self.intestatario.iva)
        hsizer.Add(self.aliquota,0,wx.LEFT|wx.RIGHT,border=5)
        
        boxsizer.Add(hsizer,0,wx.LEFT,10)
        boxsizer.AddSpacer(10)
        self.movimenta=wx.CheckBox(self,label='Movimenta Magazzino')
        boxsizer.Add(self.movimenta,0,wx.LEFT,10)
        #boxsizer.AddSpacer(10)
        #boxsizer.AddSpacer(10)
        self.SetSizer(boxsizer)
        self.Layout()
    
    def _validate_sconti(self):
        try:
            validate_sconti(self.sconti.get_value())
        except exception.KoroValidationError,inst:
            wx.GetApp().show_error(inst)
            self.sconti.clear()
    
    def _request_prezzo(self,prodotto):
        prezzo=None
        if self.intestatario.is_fornitore():
            prezzo=prodotto.get_prezzo_fornitore(self.intestatario)
        else:
            prezzo=prodotto.get_prezzo(self.codice_listino)
        return prezzo
    
    def _lookup_cancel_callback(self):
        self.ID_prodotto.clear()
        self.cod_prod_forn.clear()
        self.prezzo.clear()
    
    def _request_add_product(self):
        observer=wx.GetApp().get_observer()
        observer.set_context('PRODOTTI')
        descrizione=self.prodotto.get_string_value()
        fornitore=self.intestatario
        cod_prod_forn=self.cod_prod_forn.get_value()
        prezzo=self.prezzo.get_value()
        aliquota_iva=self.aliquota.get_selected_object()
        obj=observer.create_object(descrizione,
                                   fornitore,
                                   cod_prod_forn,
                                   prezzo,
                                   aliquota_iva)
        self.prodotto.set_value(obj)
        self.prodotto_changed_callback(obj)
    
    def before_close(self):
        '''Questo metodo viene chiamato quando viene cliccato il pulsante 'applica'
        nella toolbar del KoroDialog, prima di chiamare EndModal.'''
        self._validate_sconti()
        prodotto=self.prodotto.get_selected_object()
        movimenta=self.movimenta.GetValue()
        if prodotto is not None and self.intestatario.is_cliente():
            self._check_giacenza(prodotto)
        if prodotto is None and movimenta:
            msg = 'Per movimentare il magazzino occorre creare il prodotto.\n'
            question = 'Aggiungere il prodotto alla lista prodotti?'
            response = wx.GetApp().show_question(msg+question)
            if response == wx.ID_YES:
                self._request_add_product()
            else:
                self.movimenta.SetValue(False)
    
    def _check_giacenza(self, prodotto):
        if not prodotto.has_magazzino():
            return
        qta = self.quantita.get_value()
        giac=prodotto.get_giacenza()
        question = 'La quantità richiesta ({0}) supera quella in giacenza ({1}).\nContinuare comunque?'
        question = question.format(qta,giac)
        if int(qta) > int(giac):
            response = wx.GetApp().show_question(question)
            if response == wx.ID_NO:
                raise Exception()
        
    def prodotto_changed_callback(self,prodotto):
        self.ID_prodotto.set_value(prodotto.get_ID_fmt())
        self.cod_prod_forn.set_value(prodotto.get_codice_prod_forn(self.intestatario))
        prezzo=self._request_prezzo(prodotto)
        self.prezzo.set_value(prezzo)
        self.movimenta.SetValue(prodotto.has_magazzino())
        if self.intestatario.iva is None:
            self.aliquota.set_value(prodotto.aliquota_iva)
    
    def update_fields(self,riga):#riceve una riga
        self.numero=riga.numero
        self.ID_prodotto.set_value(riga.get_ID_prodotto_fmt())
        self.cod_prod_forn.set_value(riga.get_cod_prod_forn())
        self.prodotto.set_value(riga.prodotto)
        if riga.prodotto is None:
            self.prodotto.change_value(riga.descrizione_riga)
        self.prezzo.set_value(riga.prezzo)
        self.quantita.value=riga.quantita
        self.sconti.set_value(riga.sconti)
        self.aliquota.set_value(riga.iva_obj)
        self.movimenta.SetValue(riga.movimenta)
    
    def reset_fields(self):
        self.numero=-1
        self.ID_prodotto.clear()
        self.cod_prod_forn.clear()
        self.prezzo.clear()
        self.aliquota.clear()
        self.prodotto.clear()
        self.sconti.clear()
        self.quantita.set_value('1')
    
    def update_object(self,obj):#riceve un documento
        '''Chiede di aggiungere il fornitore al prodotto se non presente.'''
        prezzo=self.prezzo.get_value()
        aliquota=self.aliquota.get_selected_object()
        sconti=self.sconti.get_value()
        prodotto=self.prodotto.get_selected_object()
        descrizione=self.prodotto.get_string_value()
        cod_prod_forn=self.cod_prod_forn.get_value()
        quantita=self.quantita.value
        movimenta=self.movimenta.GetValue()
        try:
            obj.save_riga(numero=self.numero,
                      descrizione=descrizione,
                      prodotto=prodotto,
                      cod_prod_forn=cod_prod_forn,
                      prezzo=prezzo,
                      iva=aliquota,
                      sconti=sconti,
                      quantita=quantita,
                      movimenta=movimenta)
        except exception.KoroIncompleteObject,inst:
            response=wx.GetApp().show_question(inst.message+"\nAggiungere il fornitore al prodotto?")
            if response==wx.ID_YES:
                prodotto.add_info_fornitore(self.intestatario,
                                            cod_prod_forn,
                                            prezzo,
                                            False)


#===============================================================================
# RigaPreventivoPanel
#===============================================================================
class RigaVenditaPanel(wx.Panel):
    '''Panel contenente i campi per l'inserimento/modifica di una riga documento di vendita.'''
    def __init__(self,*args,**kwargs):
        self.intestatario=kwargs.pop('intestatario')
        self.codice_listino=kwargs.pop('codice_listino',None)
        wx.Panel.__init__(self,*args,**kwargs)
        self.numero=-1
        self.SetClientSize((390,340))
        boxsizer=wx.BoxSizer(wx.VERTICAL)
        boxsizer.AddSpacer(10)
        hsizer=wx.BoxSizer()
        self.ID_prodotto=co.LabelTextCtrl(self,size=(50,-1),label='ID',
                                          orientation=wx.VERTICAL,
                                          mstyle=co.mTE_READ_ONLY)
        hsizer.Add(self.ID_prodotto,0,wx.LEFT|wx.RIGHT,border=5)
        
#        self.barcode = co.LabelTextCtrl(self,size=(240,-1),
#                                              label='Codice a Barre',
#                                              orientation=wx.VERTICAL)
#        hsizer.Add(self.barcode,0,wx.LEFT|wx.RIGHT,border=5)
        
        boxsizer.Add(hsizer,0,wx.LEFT,10)
        
        boxsizer.AddSpacer(10)
        self.prodotto = co.LabelLookupCtrl(self,size=(300, -1),
                                           label='Prodotto',style=0,
                                           orientation=wx.VERTICAL,
                                           view='descrizione')
        self.prodotto.set_lookup_context(lookup.LOOKUP_PRODOTTI)
        self.prodotto.show_cancel_button()
        #self.prodotto.set_filter(self.fornitore)
        self.prodotto.bind(co.EVT_AFTER_LOOKUP,self.prodotto_changed_callback)
        self.prodotto.bind(co.KEVT_AFTER_LOOKUP_CANCEL,self._lookup_cancel_callback)
        boxsizer.Add(self.prodotto,0,wx.LEFT,border=15)
        
        #boxsizer.Add(hsizer,0,wx.LEFT,10)
        boxsizer.AddSpacer(10)
        hsizer=wx.BoxSizer()
        self.prezzo = co.KValutaCtrl(parent=self,size=(150,-1),label='Prezzo',orientation=wx.VERTICAL)
        hsizer.Add(self.prezzo,0,wx.LEFT|wx.RIGHT,border=5)
        
        #boxsizer.AddSpacer(10)
        #self.quantita = co.LabelTextCtrl(parent=self,size=(140,-1),label='Quantità',orientation=wx.VERTICAL)
        self.quantita=co.KQuantityCtrl(self,size=(140,-1),label='Quantità',orientation=wx.VERTICAL)
        self.quantita.value=1
        hsizer.Add(self.quantita,0,wx.LEFT|wx.RIGHT,border=5)
        
        boxsizer.Add(hsizer,0,wx.LEFT,10)
        
        boxsizer.AddSpacer(10)
        
        hsizer=wx.BoxSizer()
        self.sconti = co.LabelTextCtrl(parent=self,size=(150,-1),label='Sconti',
                                       orientation=wx.VERTICAL)#, ontext = self._validate_sconti)
        self.sconti.set_value(self.intestatario.sconti)
        hsizer.Add(self.sconti,0,wx.LEFT|wx.RIGHT,border=5)
        
        self.aliquota = co.IvaCtrl(parent=self,orientation=wx.VERTICAL)
        if self.intestatario is not None:
            self.aliquota.set_value(self.intestatario.iva)
        hsizer.Add(self.aliquota,0,wx.LEFT|wx.RIGHT,border=5)
        
        boxsizer.Add(hsizer,0,wx.LEFT,10)
        boxsizer.AddSpacer(10)
        self.movimenta=wx.CheckBox(self,label='Movimenta Magazzino')
        boxsizer.Add(self.movimenta,0,wx.LEFT,10)
        #boxsizer.AddSpacer(10)
        #boxsizer.AddSpacer(10)
        self.SetSizer(boxsizer)
        self.Layout()
    
    def _validate_sconti(self):
        try:
            validate_sconti(self.sconti.get_value())
        except exception.KoroValidationError,inst:
            wx.GetApp().show_error(inst)
            self.sconti.clear()
    
    def _request_prezzo(self,prodotto):
        prezzo=prodotto.get_prezzo(self.codice_listino)
        return prezzo
    
    def _lookup_cancel_callback(self):
        self.ID_prodotto.clear()
        #self.cod_prod_forn.clear()
        self.prezzo.clear()
        self.movimenta.Enable()
    
    def _request_add_product(self):
        observer = wx.GetApp().get_observer()
        observer.set_context('PRODOTTI')
        descrizione = self.prodotto.get_string_value()
        fornitore = None
        cod_prod_forn = None
        prezzo = self.prezzo.get_value()
        aliquota_iva = self.aliquota.get_selected_object()
        obj = observer.create_object(descrizione,
                                   fornitore,
                                   cod_prod_forn,
                                   prezzo,
                                   aliquota_iva)
        self.prodotto.set_value(obj)
        self.prodotto_changed_callback(obj)
    
    def before_close(self):
        '''Questo metodo viene chiamato quando viene cliccato il pulsante 'applica'
        nella toolbar del KoroDialog, prima di chiamare EndModal.'''
        self._validate_sconti()
        prodotto = self.prodotto.get_selected_object()
        movimenta = self.movimenta.GetValue()
        if prodotto is not None and self.intestatario.is_cliente():
            self._check_giacenza(prodotto)
        if prodotto is None and movimenta:
            msg = 'Per movimentare il magazzino occorre creare il prodotto.\n'
            question = 'Aggiungere il prodotto alla lista prodotti?'
            response = wx.GetApp().show_question(msg+question)
            if response == wx.ID_YES:
                self._request_add_product()
            else:
                self.movimenta.SetValue(False)
    
    def _check_giacenza(self,prodotto):
        if not prodotto.has_magazzino():
            return
        qta = self.quantita.get_value()
        giac = prodotto.get_giacenza()
        question = 'La quantità richiesta ({0}) supera quella in giacenza ({1}).\nContinuare comunque?'
        question = question.format(qta,giac)
        if int(qta) > int(giac):
            response = wx.GetApp().show_question(question)
            if response == wx.ID_NO:
                raise Exception()
        
    def prodotto_changed_callback(self,prodotto):
        self.ID_prodotto.set_value(prodotto.get_ID_fmt())
        #self.cod_prod_forn.set_value(prodotto.get_codice_prod_forn(self.intestatario))
        prezzo = self._request_prezzo(prodotto)
        self.prezzo.set_value(prezzo)
        self.movimenta.SetValue(prodotto.has_magazzino())
        self.movimenta.Enable(prodotto.has_magazzino())
        if self.intestatario.iva is None:
            self.aliquota.set_value(prodotto.aliquota_iva)
    
    def update_fields(self,riga):#riceve una riga
        self.numero = riga.numero
        self.ID_prodotto.set_value(riga.get_ID_prodotto_fmt())
        #self.cod_prod_forn.set_value(riga.get_cod_prod_forn())
        self.prodotto.set_value(riga.prodotto)
        if riga.prodotto is None:
            self.prodotto.set_string_value(riga.descrizione_riga)
        self.prezzo.set_value(riga.prezzo)
        self.quantita.value = riga.quantita
        self.sconti.set_value(riga.sconti)
        self.aliquota.set_value(riga.iva_obj)
        self.movimenta.SetValue(riga.movimenta)
    
    def reset_fields(self):
        self.numero = -1
        self.ID_prodotto.clear()
        #self.cod_prod_forn.clear()
        self.prezzo.clear()
        self.aliquota.clear()
        self.prodotto.clear()
        self.sconti.clear()
        self.quantita.value=1
        self.movimenta.Enable()
    
    def update_object(self,obj):#riceve un documento
        '''Chiede di aggiungere il fornitore al prodotto se non presente.'''
        prezzo = self.prezzo.get_value()
        aliquota = self.aliquota.get_selected_object()
        sconti = self.sconti.get_value()
        prodotto = self.prodotto.get_selected_object()
        descrizione = self.prodotto.get_string_value()
        #cod_prod_forn=self.cod_prod_forn.get_value()
        quantita = self.quantita.value
        movimenta=self.movimenta.GetValue()
#        try:
        obj.save_riga(numero = self.numero,
                      descrizione = descrizione,
                      prodotto = prodotto,
                      #cod_prod_forn=cod_prod_forn,
                      prezzo = prezzo,
                      iva = aliquota,
                      sconti = sconti,
                      quantita = quantita,
                      movimenta=movimenta
                      )
#        except exception.KoroIncompleteObject,inst:
#            response=wx.GetApp().show_question(inst.message+"\nAggiungere il fornitore al prodotto?")
#            if response==wx.ID_YES:
#                prodotto.add_info_fornitore(self.intestatario,
#                                            cod_prod_forn,
#                                            prezzo,
#                                            False)


#===============================================================================
# RigaPreventivoPanel
#===============================================================================
class RigaPreventivoPanel(wx.Panel):
    '''Panel contenente i campi per l'inserimento/modifica di una riga documento di vendita.'''
    def __init__(self,*args,**kwargs):
        self.intestatario=kwargs.pop('intestatario')
        self.codice_listino=kwargs.pop('codice_listino',None)
        wx.Panel.__init__(self,*args,**kwargs)
        self.numero=-1
        self.SetClientSize((390,310))
        boxsizer=wx.BoxSizer(wx.VERTICAL)
        boxsizer.AddSpacer(10)
        hsizer=wx.BoxSizer()
        self.ID_prodotto=co.LabelTextCtrl(self,size=(50,-1),label='ID',
                                          orientation=wx.VERTICAL,
                                          mstyle=co.mTE_READ_ONLY)
        hsizer.Add(self.ID_prodotto,0,wx.LEFT|wx.RIGHT,border=5)
        
#        self.barcode = co.LabelTextCtrl(self,size=(240,-1),
#                                              label='Codice a Barre',
#                                              orientation=wx.VERTICAL)
#        hsizer.Add(self.barcode,0,wx.LEFT|wx.RIGHT,border=5)
        
        boxsizer.Add(hsizer,0,wx.LEFT,10)
        
        boxsizer.AddSpacer(10)
        self.prodotto = co.LabelLookupCtrl(self,size=(300, -1),
                                           label='Prodotto',style=0,
                                           orientation=wx.VERTICAL,
                                           view='descrizione')
        self.prodotto.set_lookup_context(lookup.LOOKUP_PRODOTTI)
        self.prodotto.show_cancel_button()
        #self.prodotto.set_filter(self.fornitore)
        self.prodotto.bind(co.EVT_AFTER_LOOKUP,self.prodotto_changed_callback)
        self.prodotto.bind(co.KEVT_AFTER_LOOKUP_CANCEL,self._lookup_cancel_callback)
        boxsizer.Add(self.prodotto,0,wx.LEFT,border=15)
        
        #boxsizer.Add(hsizer,0,wx.LEFT,10)
        boxsizer.AddSpacer(10)
        hsizer=wx.BoxSizer()
        self.prezzo = co.KValutaCtrl(parent=self,size=(150,-1),label='Prezzo',orientation=wx.VERTICAL)
        hsizer.Add(self.prezzo,0,wx.LEFT|wx.RIGHT,border=5)
        
        #boxsizer.AddSpacer(10)
        #self.quantita = co.LabelTextCtrl(parent=self,size=(140,-1),label='Quantità',orientation=wx.VERTICAL)
        self.quantita=co.KQuantityCtrl(self,size=(140,-1),label='Quantità',orientation=wx.VERTICAL)
        self.quantita.value=1
        hsizer.Add(self.quantita,0,wx.LEFT|wx.RIGHT,border=5)
        
        boxsizer.Add(hsizer,0,wx.LEFT,10)
        
        boxsizer.AddSpacer(10)
        
        hsizer=wx.BoxSizer()
        self.sconti = co.LabelTextCtrl(parent=self,size=(150,-1),label='Sconti',orientation=wx.VERTICAL)
        self.sconti.set_value(self.intestatario.sconti)
        hsizer.Add(self.sconti,0,wx.LEFT|wx.RIGHT,border=5)
        
        self.aliquota = co.IvaCtrl(parent=self,orientation=wx.VERTICAL)
        if self.intestatario is not None:
            self.aliquota.set_value(self.intestatario.iva)
        hsizer.Add(self.aliquota,0,wx.LEFT|wx.RIGHT,border=5)
        
        boxsizer.Add(hsizer,0,wx.LEFT,10)
#        boxsizer.AddSpacer(10)
#        self.movimenta=wx.CheckBox(self,label='Movimenta Magazzino')
#        boxsizer.Add(self.movimenta,0,wx.LEFT,10)
        #boxsizer.AddSpacer(10)
        #boxsizer.AddSpacer(10)
        self.SetSizer(boxsizer)
        self.Layout()
    
    def _validate_sconti(self):
        try:
            validate_sconti(self.sconti.get_value())
        except exception.KoroValidationError,inst:
            wx.GetApp().show_error(inst)
            self.sconti.clear()
    
    def _request_prezzo(self,prodotto):
        prezzo=prodotto.get_prezzo(self.codice_listino)
        return prezzo
    
    def _lookup_cancel_callback(self):
        self.ID_prodotto.clear()
        self.cod_prod_forn.clear()
        self.prezzo.clear()
    
#    def _request_add_product(self):
#        observer = wx.GetApp().get_observer()
#        observer.set_context('PRODOTTI')
#        descrizione = self.prodotto.get_string_value()
#        fornitore = None
#        cod_prod_forn = None
#        prezzo = self.prezzo.get_value()
#        aliquota_iva = self.aliquota.get_selected_object()
#        obj = observer.create_object(descrizione,
#                                   fornitore,
#                                   cod_prod_forn,
#                                   prezzo,
#                                   aliquota_iva)
#        self.prodotto.set_value(obj)
#        self.prodotto_changed_callback(obj)
    
    def before_close(self):
        '''Questo metodo viene chiamato quando viene cliccato il pulsante 'applica'
        nella toolbar del KoroDialog, prima di chiamare EndModal.'''
        self._validate_sconti()
#        prodotto = self.prodotto.get_selected_object()
#        movimenta = self.movimenta.GetValue()
#        if prodotto is not None and self.intestatario.is_cliente():
#            self._check_giacenza(prodotto)
#        if prodotto is None and movimenta:
#            msg = 'Per movimentare il magazzino occorre creare il prodotto.\n'
#            question = 'Aggiungere il prodotto alla lista prodotti?'
#            response = wx.GetApp().show_question(msg+question)
#            if response == wx.ID_YES:
#                self._request_add_product()
#            else:
#                self.movimenta.SetValue(False)
    
#    def _check_giacenza(self,prodotto):
#        qta = self.quantita.get_value()
#        giac = prodotto.get_giacenza()
#        question = 'La quantità richiesta ({0}) supera quella in giacenza ({1}).\nContinuare comunque?'
#        question = question.format(qta,giac)
#        if int(qta) > int(giac):
#            response = wx.GetApp().show_question(question)
#            if response == wx.ID_NO:
#                raise Exception()
        
    def prodotto_changed_callback(self,prodotto):
        self.ID_prodotto.set_value(prodotto.get_ID_fmt())
        #self.cod_prod_forn.set_value(prodotto.get_codice_prod_forn(self.intestatario))
        prezzo = self._request_prezzo(prodotto)
        self.prezzo.set_value(prezzo)
        #self.movimenta.SetValue(prodotto.has_magazzino())
        if self.intestatario.iva is None:
            self.aliquota.set_value(prodotto.aliquota_iva)
    
    def update_fields(self,riga):#riceve una riga
        self.numero = riga.numero
        self.ID_prodotto.set_value(riga.get_ID_prodotto_fmt())
        #self.cod_prod_forn.set_value(riga.get_cod_prod_forn())
        self.prodotto.set_value(riga.prodotto)
        if riga.prodotto is None:
            self.prodotto.set_string_value(riga.descrizione_riga)
        self.prezzo.set_value(riga.prezzo)
        self.quantita.value = riga.quantita
        self.sconti.set_value(riga.sconti)
        self.aliquota.set_value(riga.iva_obj)
        #self.movimenta.SetValue(riga.movimenta)
    
    def reset_fields(self):
        self.numero = -1
        self.ID_prodotto.clear()
        #self.cod_prod_forn.clear()
        self.prezzo.clear()
        self.aliquota.clear()
        self.prodotto.clear()
        self.sconti.clear()
        self.quantita.value=1
    
    def update_object(self,obj):#riceve un documento
        '''Chiede di aggiungere il fornitore al prodotto se non presente.'''
        prezzo = self.prezzo.get_value()
        aliquota = self.aliquota.get_selected_object()
        sconti = self.sconti.get_value()
        prodotto = self.prodotto.get_selected_object()
        descrizione = self.prodotto.get_string_value()
        #cod_prod_forn=self.cod_prod_forn.get_value()
        quantita = self.quantita.value
        #movimenta=self.movimenta.GetValue()
#        try:
        obj.save_riga(numero = self.numero,
                      descrizione = descrizione,
                      prodotto = prodotto,
                      #cod_prod_forn=cod_prod_forn,
                      prezzo = prezzo,
                      iva = aliquota,
                      sconti = sconti,
                      quantita = quantita,
                      #movimenta=movimenta
                      )
#        except exception.KoroIncompleteObject,inst:
#            response=wx.GetApp().show_question(inst.message+"\nAggiungere il fornitore al prodotto?")
#            if response==wx.ID_YES:
#                prodotto.add_info_fornitore(self.intestatario,
#                                            cod_prod_forn,
#                                            prezzo,
#                                            False)        


#===============================================================================
# RigaRegFattFornPanel
#===============================================================================
class RigaRegFattFornPanel(wx.Panel):
    def __init__(self,*args,**kwargs):
        wx.Panel.__init__(self,*args,**kwargs)
        self.SetClientSize((400,200))
        self.numero=-1
#        self.importo=co.LabelTextCtrl(self,label='Importo',valuta=True)
        self.importo=co.KValutaCtrl(self,label='Importo')
        self.descrizione=co.LabelTextCtrl(self,label='Descrizione')        
        #self.sconti=co.LabelTextCtrl(self,label='Sconti')        
        self.aliquota=co.IvaCtrl(self)
        
        self._layout()
    
#    def _validate_sconti(self):
#        try:
#            validate_sconti(self.sconti.get_value())
#        except exception.KoroValidationError,inst:
#            wx.GetApp().show_error(inst)
#            self.sconti.clear()
    
    def _layout(self):
        boxsizer=wx.BoxSizer(wx.VERTICAL)
        
        boxsizer.Add(self.importo,0,wx.LEFT,10)
        boxsizer.Add(self.descrizione,0,wx.LEFT,10)
        #boxsizer.Add(self.sconti,0,wx.LEFT,10)
        boxsizer.Add(self.aliquota,0,wx.LEFT,10)
        self.SetSizer(boxsizer)
        self.Layout()
    
    def update_fields(self,riga):#riceve una riga
        self.numero=riga.numero
        self.importo.set_value(riga.prezzo)
        self.aliquota.set_value(riga.iva_obj)
        self.descrizione.set_value(riga.descrizione_riga)
        #self.sconti.set_value(riga.sconti)
    
    def reset_fields(self):
        self.numero=-1
        self.importo.clear()
        self.aliquota.clear()
        self.descrizione.clear()
        #self.sconti.clear()
    
    def update_object(self,obj):#riceve un documento
        importo=self.importo.get_value()
        aliquota=self.aliquota.get_selected_object()
        sconti=''#self.sconti.get_value()
        descrizione=self.descrizione.get_value()
        obj.dettaglio.save_riga(numero=self.numero,
                                descrizione=descrizione,
                                prezzo=importo,
                                iva=aliquota,
                                sconti=sconti)
    
    def before_close(self):
        self._validate_sconti()


#===============================================================================
# DettaglioDocumentoSPanel
#===============================================================================
class DettaglioDocumentoSPanel(BasePanel):
    '''Contiene una lista (co.KoroListCtrl) gestita dal list manager KoroListCtrlManager
     delle righe documento la toolbar(DettaglioToolBar) per la gestione delle righe.
    
    Usa e modifica l'oggetto documento posseduto dalla classe wrapper(ListPage).
    @param parent: è il notebook del DocumentoPanel. Quindi il GrandParent è il DocumentoPanel.
    @param wrapper: è la pagina DocumentoListPage che possiede l'oggetto su cui si sta lavorando. 
    '''
    def __init__(self,*args,**kwargs):
        BasePanel.__init__(self,*args,**kwargs)
        #self._dettaglio=None
        #self._reset_dettaglio()
        self._toolbar_dettaglio=tb=co.DettaglioToolBar(self)
#        tb.SetToolBitmapSize(wx.Size(16,16))
#        tb.AddLabelTool(ID_RIGA_NEW, "Nuovo", wx.ArtProvider_GetBitmap(wx.ART_NEW,wx.ART_MENU))
#        tb.AddLabelTool(ID_RIGA_ADD, "Salva", wx.ArtProvider_GetBitmap(wx.ART_ADD_BOOKMARK,wx.ART_MENU))
#        tb.AddLabelTool(ID_RIGA_DEL, "Elimina", wx.ArtProvider_GetBitmap(wx.ART_DEL_BOOKMARK,wx.ART_MENU))
        tb.SetBackgroundColour("#BACAD9")
        tb.Realize()
           
        self.dettaglio_list_manager=co.KoroListCtrlManager()
        self.dettaglio_list_manager.set_managed_list(co.KoroListCtrl(self))
        self.dettaglio_list_manager.bind_callback(wx.EVT_LIST_ITEM_ACTIVATED, self.edit_riga_callback)               
        self.SetBackgroundColour("#BACAD9")
        
        self.__editable=True
        self._layout()
        self.__bind()
        #self._set_riga_tool_state(False,False,False)
    
    def _layout(self):
        boxsizer=wx.BoxSizer(wx.VERTICAL)
        
        boxsizer.Add(self._toolbar_dettaglio,0,flag=wx.ALL,border=0)
                        
        self._configure_list()        
        boxsizer.Add(self.dettaglio_list_manager.get_managed_list(),0,wx.ALL|wx.EXPAND,border=1)
        
        
        self.SetBackgroundColour("#BACAD9")        
        self.SetSizer(boxsizer)
        self.SetAutoLayout(True)
        self.Layout()
    
    def _configure_list(self):#TODO: questo è per arrivo
        self.dettaglio_list_manager.set_list_size((500,270))
        self.dettaglio_list_manager.set_columns((co.Column('ID',40,'get_ID_prodotto_fmt'),
                                                 co.Column('Cod.Forn.',100,'get_cod_prod_forn'),
                                                 co.Column('Descrizione',290,'get_descrizione'),
                                                 co.Column('Prezzo Unit.',100,'get_prezzo_fmt',wx.LIST_FORMAT_RIGHT),
                                                 co.Column('Sconti',90,'get_sconti'),
                                                 co.Column("Qta",50,'get_quantita',wx.LIST_FORMAT_RIGHT),
                                                 co.Column("Totale",100,'get_totale_fmt',wx.LIST_FORMAT_RIGHT),
                                                 co.Column("Iva",100,'get_codice_iva_riga'),
                                                     ))
    
    def __bind(self):
        #self.Bind(co.EVT_PICKER,self._on_iva_picker,id=ID_IVA_PICKER)
        #self.Bind(wx.EVT_LIST_ITEM_SELECTED,self._on_riga_selected,self.list_ctrl)
        #self.Bind(wx.EVT_COMBOBOX,self._on_product_selected,id=self.prodotto.get_id())    
        self._toolbar_dettaglio.Bind(wx.EVT_TOOL,self._new_riga_handler,id=wx.ID_NEW)
        self._toolbar_dettaglio.Bind(wx.EVT_TOOL,self._del_riga_handler,id=wx.ID_DELETE)
        self._toolbar_dettaglio.Bind(wx.EVT_TOOL,self._edit_riga_handler,id=wx.ID_EDIT)
        #self.prodotto.bind(co.EVT_AFTER_LOOKUP,self._on_product_selected)
        #self.set_accelerator_table([(wx.ACCEL_NORMAL,wx.WXK_F2,wx.ID_NEW)])
    
    def _new_riga_handler(self,evt):
        subheader="{0} numero {1}".format(self.wrapper.get_object().get_tipo_documento_fmt(),
                                          self.GrandParent.get_numero_documento())        
        dlg=dialogs.KoroDialog(self,header='Nuova Riga',subheader=subheader,toolbar=True)
        dlg.set_panel(self._get_riga_panel())
        ret_code=dlg.show()
        if ret_code==wx.ID_CLOSE:
            obj=self.wrapper.get_object()#wrapper è la ListPage
            dlg.update_object(obj)            
            self.dettaglio_list_manager.load(obj.dettaglio)
            self._genera_dettaglio_changed_event(obj)
    
    def _del_riga_handler(self,evt):
        riga=self.dettaglio_list_manager.get_selected_object()
        if riga is None:
            return
        obj=self.wrapper.get_object()
        obj.remove_riga(riga)
        self.dettaglio_list_manager.load(obj.dettaglio)
        self._genera_dettaglio_changed_event(obj)
    
    def _edit_riga_handler(self,evt):
        pass#not implemented. forse non lo sarà mai
    
    def edit_riga_callback(self,obj,index):#riceve una riga
        subheader="{0} numero {1}".format(self.wrapper.get_object().get_tipo_documento_fmt(),
                                          self.GrandParent.get_numero_documento())
        dlg=dialogs.KoroDialog(self,header='Modifica Riga',subheader=subheader,toolbar=True)
        dlg.set_panel(self._get_riga_panel())
        dlg.update(obj)
        ret_code=dlg.show()
        if ret_code==wx.ID_CLOSE:
            obj=self.wrapper.get_object()#wrapper è la ListPage
            dlg.update_object(obj)
            self.dettaglio_list_manager.load(obj.dettaglio)
            self._genera_dettaglio_changed_event(obj)
    
    def _genera_dettaglio_changed_event(self,obj):
        evento=wx.PyCommandEvent(EVT_DETTAGLIO_CHANGED.typeId,self.GetId())        
        evento.object=obj
        self.GetEventHandler().ProcessEvent(evento)
    
    def _get_riga_panel(self):
        return RigaDocumentoPanel(self)
    
    def _set_editable(self,editable=True):
        self.__editable=editable
    
    def _is_editable(self):
        return self.__editable    
    
    def update_fields(self,obj):
        '''Aggiorna i campi della maschera con i valori dell'oggetto documento.'''
        print self.__class__.__name__,'.update_fields'
        self.dettaglio_list_manager.load(obj.dettaglio)
        
        
    def update_object(self,obj):
        '''Questo metodo e' deprecato. Questa classe usa direttamente l'oggetto documento
         posseduto dalla classe wrapper.'''
        print self.__class__.__name__,'.update_object'
#        if len(obj.dettaglio)==0 or \
#        len(obj.dettaglio)!=len(self._dettaglio):#fix bug(1) anomalia inserimento righe
#            del obj.dettaglio
#            obj.dettaglio=self._dettaglio

    def reset_fields(self):
        '''Questo metodo e' deprecato. non viene mai chiamato.'''
        print 'DettaglioOrdinePanel.reset_fields'
        
    
    def get_righe_count(self):
        '''Restituisce il numero dirighe doumento.
        In teoria non serve. Basta fare il controllo sull'oggetto documento.'''
        return self.list_ctrl.GetItemCount()
    
    def _reset_dettaglio(self):
        '''Questo metodo e' deprecato. Questa classe usa direttamente l'oggetto documento
         posseduto dalla classe wrapper.'''
#        observer=self.get_contextual_observer()
#        self._dettaglio=observer.get_object_class().get_new_dettaglio()


#===============================================================================
# DettaglioArrivoMerceSPanel
#===============================================================================
class DettaglioArrivoMerceSPanel(DettaglioDocumentoSPanel):
    def __init__(self,*args,**kwargs):
        DettaglioDocumentoSPanel.__init__(self,*args,**kwargs)
    
    def _get_riga_panel(self):
        return RigaAcquistoPanel(self,intestatario=self.GrandParent.get_intestatario())
    
    def _configure_list(self):
        self.dettaglio_list_manager.set_list_size((500,270))
        self.dettaglio_list_manager.set_columns((co.Column('ID',40,'get_ID_prodotto_fmt'),
                                                 co.Column('Cod.Forn.',100,'get_cod_prod_forn'),
                                                 co.Column('Descrizione',290,'get_descrizione'),
                                                 co.Column('Prezzo Unit.',100,'get_prezzo_fmt',wx.LIST_FORMAT_RIGHT),
                                                 co.Column('Sconti',90,'get_sconti'),
                                                 co.Column("Qta",50,'get_quantita',wx.LIST_FORMAT_RIGHT),
                                                 co.Column("Iva",40,'get_codice_iva_riga'),
                                                 co.Column('Magaz.',46,'movimenta_fmt',wx.LIST_FORMAT_CENTER),
                                                 co.Column("Totale",100,'get_totale_fmt',wx.LIST_FORMAT_RIGHT),                                                 
                                                     ))
    
    def _new_riga_handler(self,evt):
        intestatario=self.GrandParent.get_intestatario()
        if intestatario is None:
            wx.GetApp().show_error('Selezionare il Fornitore')
            return
        super(DettaglioArrivoMerceSPanel,self)._new_riga_handler(evt)

#===============================================================================
# DettaglioRegFattFornSPanel
#===============================================================================
class DettaglioRegFattFornSPanel(DettaglioDocumentoSPanel):
    def __init__(self,*args,**kwargs):
        DettaglioDocumentoSPanel.__init__(self,*args,**kwargs)

    def _get_riga_panel(self):
        return RigaRegFattFornPanel(self)
    
    def _configure_list(self):
        self.dettaglio_list_manager.set_list_size((500,270))
        self.dettaglio_list_manager.set_columns((co.Column('Descrizione',470,'get_descrizione'),                                                 
                                                 co.Column('Sconti',90,'get_sconti'),
                                                 co.Column("Iva",100,'get_codice_iva_riga'),
                                                 co.Column("Importo",100,'get_prezzo_fmt',wx.LIST_FORMAT_RIGHT),                                                 
                                                ))
    
    def _new_riga_handler(self,evt):
        intestatario=self.GrandParent.get_intestatario()
        if intestatario is None:
            wx.GetApp().show_error('Selezionare il Fornitore')
            return
        super(DettaglioRegFattFornSPanel,self)._new_riga_handler(evt)


#===============================================================================
# DettaglioFatturaSPanel
#===============================================================================
class DettaglioFatturaSPanel(DettaglioDocumentoSPanel):
    def __init__(self,*args,**kwargs):
        DettaglioDocumentoSPanel.__init__(self,*args,**kwargs)
    
    def _get_riga_panel(self):
        return RigaVenditaPanel(self,
                                  intestatario=self.GrandParent.get_intestatario(),
                                  codice_listino=self.GrandParent.get_codice_listino())
    
    def _configure_list(self):
        self.dettaglio_list_manager.set_list_size((500,270))
        self.dettaglio_list_manager.set_columns((co.Column('ID',40,'get_ID_prodotto_fmt'),                                                 
                                                 co.Column('Descrizione',290,'get_descrizione'),
                                                 co.Column('Prezzo Unit.',100,'get_prezzo_fmt',wx.LIST_FORMAT_RIGHT),
                                                 co.Column('Sconti',90,'get_sconti'),
                                                 co.Column("Qta",50,'get_quantita',wx.LIST_FORMAT_RIGHT),
                                                 co.Column("Iva",40,'get_codice_iva_riga',wx.LIST_FORMAT_RIGHT),
                                                 co.Column('Magaz.',46,'movimenta_fmt',wx.LIST_FORMAT_CENTER),
                                                 co.Column("Totale",100,'get_totale_fmt',wx.LIST_FORMAT_RIGHT),                                                 
                                                     ))
    def _new_riga_handler(self,evt):
        intestatario=self.GrandParent.get_intestatario()
        if intestatario is None:
            wx.GetApp().show_error('Selezionare il Cliente')
            return
        super(DettaglioFatturaSPanel,self)._new_riga_handler(evt)


#===============================================================================
# DettaglioPreventivoSPanel
#===============================================================================
class DettaglioPreventivoSPanel(DettaglioDocumentoSPanel):
    def __init__(self,*args,**kwargs):
        DettaglioDocumentoSPanel.__init__(self,*args,**kwargs)
    
    def _get_riga_panel(self):
        return RigaPreventivoPanel(self,
                                  intestatario=self.GrandParent.get_intestatario(),
                                  codice_listino=self.GrandParent.get_codice_listino())
    
    def _configure_list(self):
        self.dettaglio_list_manager.set_list_size((500,270))
        self.dettaglio_list_manager.set_columns((co.Column('ID',40,'get_ID_prodotto_fmt'),                                                 
                                                 co.Column('Descrizione',290,'get_descrizione'),
                                                 co.Column('Prezzo Unit.',100,'get_prezzo_fmt',wx.LIST_FORMAT_RIGHT),
                                                 co.Column('Sconti',90,'get_sconti'),
                                                 co.Column("Qta",50,'get_quantita',wx.LIST_FORMAT_RIGHT),
                                                 co.Column("Iva",40,'get_codice_iva_riga',wx.LIST_FORMAT_RIGHT),
                                                 co.Column("Totale",100,'get_totale_fmt',wx.LIST_FORMAT_RIGHT),                                                 
                                                     ))
    def _new_riga_handler(self,evt):
        intestatario=self.GrandParent.get_intestatario()
        if intestatario is None:
            wx.GetApp().show_error('Selezionare il Cliente')
            return
        super(DettaglioPreventivoSPanel,self)._new_riga_handler(evt)


#===============================================================================
# DocumentoBasePanel
#===============================================================================
class DocumentoBasePanel(BasePanel,TotaliManager):
    '''Classe base per le maschere documenti.
    Non ha layout, ma contiene i seguenti oggetti grafici comuni a tutti i documenti:
    - il campo _toolbar di tipo co.DocumentoToolBar
    - il campo numero di tipo co.LabelTextCtrl
    - il campo intestatario di tipo co.LabelLookupCtrl
    - il campo data di tipo co.KDateCtrl
    - il campo notebook di tipo co.KoroNotebook
    - il campo dettaglio_doc_panel di tipo DettaglioDocumentoPanel (pagina del notebook)
    - il campo totali di tipo co.TotaliCtrl (ereditato da pa.TotaliManager) 
    '''
    TITLE=''
    def __init__(self,*args,**kwargs):                
        BasePanel.__init__(self,*args,**kwargs)
        TotaliManager.__init__(self)
        self.Show(False)
        
        self._toolbar=co.DocumentoToolBar(self)
        self._configure_documento_toolbar()
               
        self.numero = co.LabelTextCtrl(parent=self,label='Numero',size=(60,-1),mstyle=co.mTE_READ_ONLY,orientation=wx.VERTICAL)#co.mTE_REQUIRED|co.mTE_DIGIT_ONLY|co.mTE_ZFILL)
#       
        self.intestatario = co.LabelLookupCtrl(self,label='',size=(250, -1),orientation=wx.VERTICAL,view='ragione_sociale')
#       
        #self.data = co.LabelDateCtrl(self,label='',orientation=wx.VERTICAL)
        self.data = co.KDateCtrl(self,label='',orientation=wx.VERTICAL)
        
        #self.listino=co.ListinoCtrl(self,orientation=wx.VERTICAL)
#       
        #fnbstyle=fnb.FNB_NODRAG|fnb.FNB_NO_X_BUTTON|fnb.FNB_NO_NAV_BUTTONS
        #fnbstyle=fnb.FNB_NODRAG|fnb.FNB_NO_X_BUTTON|fnb.FNB_NO_NAV_BUTTONS|fnb.FNB_FANCY_TABS
        #fnbstyle=fnb.FNB_NODRAG|fnb.FNB_NO_X_BUTTON|fnb.FNB_NO_NAV_BUTTONS|fnb.FNB_VC8
        #fnbstyle=fnb.FNB_NODRAG|fnb.FNB_NO_X_BUTTON|fnb.FNB_NO_NAV_BUTTONS|fnb.FNB_VC71       
        self.notebook = co.KoroNotebook(self)#, wx.ID_ANY, style=fnbstyle)
        #wrapper è la ListPage perché in questo momento il Pnel è creato con Parent=ListPage
        #Successivamente l'ObjectViewer farà il Reparent
        self.dettaglio_doc_panel = p1 = self._get_dettaglio_panel_class()(self.notebook,wrapper=self.Parent)
        self.dettaglio_doc_panel.Bind(EVT_DETTAGLIO_CHANGED,self._dettaglio_changed_handler)       
        self.notebook.AddPage(p1,'Dettaglio')        
        #if self._with_spese:
        #    self.spese=co.SpeseCtrl(self)
        
        totali=co.TotaliCtrl(self)
        self.set_totali_ctrl(totali)
        
        
        #self.__bind()
    
    def _layout(self):
        '''OVERRIDE IN SUBCLASS.'''
        pass
        
    
#    def _on_close(self,evt):
#        print self.__class__.__name__,'_on_close'
#        self.Parent.Close()
    
    def _configure_documento_toolbar(self):#override in subclass
        '''L'overriding di questo metodo permette alle varie sottoclassi
         di personalizzare la toolbar del documento. 
         Inoltre questo è un buon posto dove chiamare self._toolbar.realize()'''
        self._toolbar.realize()
    
    def _dettaglio_changed_handler(self,evt):
        self.aggiorna_totali(evt.object)
    
    def _get_dettaglio_panel_class(self):
        return DettaglioDocumentoSPanel
        
#    def __bind(self):
#        self.intestatario.bind(co.EVT_AFTER_LOOKUP,self._intestatario_changed_callback)
    
#    def _intestatario_changed_callback(self,intestatario):
#        self.dettaglio_doc_panel.set_intestatario(intestatario)
    
#    def _is_valid(self):#TODO:
#        righe_cont=self.dettaglio_doc_panel.get_righe_count()
#        if not righe_cont>0:
#            wx.GetApp().show_message("Impossibile procedere: nessuna riga in dettaglio.")
#            return False
#        return True
            
#    def _on_intestatario_selected(self,intestatario):#TODO:gestire il caso vendita al banco senza cliente
#        print '_on_fornitore_selected'
#        self.listino.set_string_selection(intestatario.listino.codice)                
        #self.dettaglio_doc_panel.prodotto.enable(True)
        #self.dettaglio_doc_panel.iva_ctrl.set_string_selection(intestatario.iva.codice)
    
#    def _request_tipi_stato_ordine(self):#TODO:
#        observer=wx.GetApp().get_observer()
#        observer.set_ordini_fornitore_context()
#        return observer.action_request("tipi_stato_ordine")

    def get_toolbar(self):
        return self._toolbar
    
    def get_intestatario(self):
        return self.intestatario.get_selected_object()
    
    def get_numero_documento(self):
        return self.numero.get_value()
    
    def update_fields(self,obj):
        print self.__class__.__name__,'.update_fields'
        if obj is None:
            return
        self.numero.set_value(obj.get_numero_documento_fmt())
        self.intestatario.set_value(obj.intestatario)
        #self.intestatario.change_value(obj.intestatario)
#        if obj.intestatario is not None:
#            self.dettaglio_doc_panel.prodotto.enable(True)        
        self.data.set_value(obj.get_data_documento())    
        #self.dettaglio_doc_panel.iva_ctrl.set_value(obj.get_iva_intestatario())#TODO:gestire il caso vendita banco senza cliente
        self.dettaglio_doc_panel.update_fields(obj)
        self.aggiorna_totali(obj)

    def update_object(self,obj):
        print self.__class__.__name__,'update_object'
        #obj=self.Parent.get_object()
        #obj.set_ID(self.ID.get_value())
        obj.intestatario=self.intestatario.get_value()
        obj.data=self.data.get_value()
        self.dettaglio_doc_panel.update_object(obj)
        obj.calcola_totali()
        #return object
    
#    def _get_toolbar(self):
#        return self._toolbar

#===============================================================================
# DocumentoPanel
#===============================================================================
class DocumentoPanel(DocumentoBasePanel):
    def __init__(self,*args,**kwargs):
        DocumentoBasePanel.__init__(self,*args,**kwargs)
        self.spese=co.SpeseCtrl(self)
        self.listino=co.ListinoCtrl(self,orientation=wx.VERTICAL)
        self.__bind()

    def _configure_documento_toolbar(self):
        tb = self.get_toolbar()
        tb.add_label_tool(wx.ID_PRINT, " Stampa", images.getPrint16Bitmap())
        self.Bind(wx.EVT_TOOL, self._print_doc, id=wx.ID_PRINT)
        return DocumentoBasePanel._configure_documento_toolbar(self)

    def _print_doc(self,evt):
        print 'oooooooooooooooooooooooooooooooooo'
        evt.Skip(False)
        obj = self.Parent.get_object()
        #if obj.is_pending_object():
        #    return
        self.update_object(obj)        
        c=DocumentoCanvas(obj)
        c.print_preview()
    
    def __bind(self):
        self.spese.bind(wx.EVT_KILL_FOCUS,self._spese_changed_handler)
    
    def _spese_changed_handler(self,evt):
        print 'in documenti'
        obj=self.Parent.get_object()
        if obj is None:
            return
        self._set_spese_documento(obj)
        self.aggiorna_totali(obj)
        evt.Skip(True)
    
    def get_codice_listino(self):
        return self.listino.get_selected_object().ID
    
    def update_fields(self,obj):
        print self.__class__.__name__,'.update_fields'
        if obj is None:
            return        
        self.listino.set_value(obj.listino)        
        self.spese.set_spese(obj.spese_descr,
                             obj.spese_fk_iva,
                             obj.spese_importo)
        DocumentoBasePanel.update_fields(self,obj)
    
    def update_object(self,obj):
        print self.__class__.__name__,'update_object'
        self._set_spese_documento(obj)
        obj.set_listino(self.listino.get_selected_object())
        DocumentoBasePanel.update_object(self, obj)
    
    def _set_spese_documento(self,obj):
        obj.spese_descr=self.spese.get_descrizione()
        obj.set_iva_spese(self.spese.get_iva())
        obj.set_importo_spese(self.spese.get_importo())


#===============================================================================
# PreventivoPanel
#===============================================================================
class PreventivoPanel(DocumentoPanel):
    TITLE='Preventivi'
    def __init__(self,*args,**kwargs):
        DocumentoPanel.__init__(self,*args,**kwargs)
        self._layout()
    
    def _layout(self):
        boxsizer = wx.BoxSizer(wx.VERTICAL)
        
        #self._init_toolbar()
        boxsizer.Add(self._toolbar,0,wx.EXPAND)
        
        boxsizer.Add(wx.StaticLine(self),1,wx.EXPAND)
        
        orsizer=wx.BoxSizer()
        
        orsizer.Add(self.numero,0,wx.ALL,border=mDefaultBorder)
        
        orsizer.AddSpacer(10)
        
#        self.numero = co.LabelTextCtrl(parent=self,label='Numero',size=(55,-1),mstyle=co.mTE_READ_ONLY,orientation=wx.VERTICAL)
#        orsizer.Add(self.numero,0,wx.ALL,border=mDefaultBorder)
#        orsizer.AddSpacer(10)        
        
        self.intestatario.set_label('Cliente')
        self.intestatario.set_lookup_context(lookup.LOOKUP_CLIENTI)
        orsizer.Add(self.intestatario,0,wx.ALL,border=mDefaultBorder)
        orsizer.AddSpacer(10)
                
        self.data.set_label('Data Doc.')
        orsizer.Add(self.data,0,wx.ALL,border=mDefaultBorder)
        
        orsizer.AddSpacer(10)
        orsizer.Add(self.listino,0,wx.ALL,border=mDefaultBorder)
        
        orsizer.AddSpacer((200,1))
        
        boxsizer.Add(orsizer)        

        boxsizer.Add(self.notebook,0,wx.EXPAND,border=mDefaultBorder)
        
        orsizer=wx.BoxSizer()
        
        vsizer=wx.BoxSizer(wx.VERTICAL)
        vsizer.Add(self.spese,0,wx.TOP|wx.EXPAND,border=mDefaultBorder)
        self.commento=co.LabelTextCtrl(self,label='Commento a uso interno',size=(400,-1),orientation=wx.VERTICAL,maxlen=100)
        vsizer.Add(self.commento,0,wx.TOP,5)
        
        orsizer.Add(vsizer,0)        
        orsizer.AddStretchSpacer(1)
        
        orsizer.Add(self.get_totali_ctrl(),0,wx.TOP|wx.EXPAND|wx.GROW|wx.ALIGN_RIGHT,border=mDefaultBorder)
        
        boxsizer.Add(orsizer,0,wx.ALL|wx.EXPAND,border=5)
        self.SetSizer(boxsizer)
        boxsizer.Layout()
     
#    def _is_valid(self):#TODO:
#        righe_cont=self.dettaglio_doc_panel.get_righe_count()
#        if not righe_cont>0:
#            wx.GetApp().show_message("Impossibile procedere: nessuna riga in dettaglio.")
#            return False
#        return True
   
    def _print_doc(self,evt):
        print 'oooooooooooooooooooooooooooooooooo'
        evt.Skip(False)
        obj = self.Parent.get_object()
        #if obj.is_pending_object():
        #    self.update_object(obj)
        self.update_object(obj)       
        c=PreventivoCanvas(obj)
        c.print_preview()
   
    def _get_dettaglio_panel_class(self):
        return DettaglioPreventivoSPanel
    
    def update_fields(self,obj):
        print self.__class__.__name__,'.update_fields'
        if obj is None:
            return
        DocumentoPanel.update_fields(self, obj)
        self.commento.set_value(obj.commento_interno)

    def update_object(self,obj):
        print self.__class__.__name__,'.update_object'
        DocumentoPanel.update_object(self,obj)
        obj.commento_interno=self.commento.get_value()


#===============================================================================
# FatturaPanel
#===============================================================================
class FatturaPanel(DocumentoPanel):
    TITLE='Fattura'
    def __init__(self,*args,**kwargs):
        DocumentoPanel.__init__(self,*args,**kwargs)
        self._layout()
    
    def _layout(self):
        boxsizer = wx.BoxSizer(wx.VERTICAL)
        
        #self._init_toolbar()
        boxsizer.Add(self._toolbar,0,wx.EXPAND)
        
        boxsizer.Add(wx.StaticLine(self),1,wx.EXPAND)
        
        orsizer=wx.BoxSizer()
        
        orsizer.Add(self.numero,0,wx.ALL,border=mDefaultBorder)
        
        orsizer.AddSpacer(10)        
        
        self.intestatario.set_label('Cliente')
        self.intestatario.set_lookup_context(lookup.LOOKUP_CLIENTI)
        orsizer.Add(self.intestatario,0,wx.ALL,border=mDefaultBorder)
        orsizer.AddSpacer(10)
                
        self.data.set_label('Data Documento')
        orsizer.Add(self.data,0,wx.ALL,border=mDefaultBorder)
        
        orsizer.AddSpacer(10)
        orsizer.Add(self.listino,0,wx.ALL,border=mDefaultBorder)
        
        orsizer.AddSpacer((270,1))
        
        boxsizer.Add(orsizer)        

        boxsizer.Add(self.notebook,0,wx.EXPAND,border=mDefaultBorder)
        
        orsizer=wx.BoxSizer()
        
        orsizer.Add(self.spese,0,wx.TOP|wx.EXPAND,border=mDefaultBorder)
        
        orsizer.AddStretchSpacer(1)
        
        orsizer.Add(self.get_totali_ctrl(),0,wx.TOP|wx.EXPAND|wx.GROW|wx.ALIGN_RIGHT,border=mDefaultBorder)
        
        boxsizer.Add(orsizer,0,wx.ALL|wx.EXPAND,border=5)
        self.SetSizer(boxsizer)
        boxsizer.Layout()
     
#    def _is_valid(self):#TODO:
#        righe_cont=self.dettaglio_doc_panel.get_righe_count()
#        if not righe_cont>0:
#            wx.GetApp().show_message("Impossibile procedere: nessuna riga in dettaglio.")
#            return False
#        return True
    
    def _get_dettaglio_panel_class(self):
        return DettaglioFatturaSPanel
    
    def update_fields(self,obj):
        print self.__class__.__name__,'.update_fields'
        #if object is None:è nella classe madre
        #    return        
        DocumentoPanel.update_fields(self, obj)

    def update_object(self,obj):
        print self.__class__.__name__,'.update_object'        
        DocumentoPanel.update_object(self,obj)


#===============================================================================
# ArrivoMercePanel
#===============================================================================
class ArrivoMercePanel(DocumentoPanel):
    TITLE='Arrivo Merce'
    def __init__(self,*args,**kwargs):
        DocumentoPanel.__init__(self,*args,**kwargs)
        self._layout()

    def _configure_documento_toolbar(self):
        tb=self.get_toolbar()
        tb.AddLabelTool(ID_REG_FATT_FORN,
                        " Reg.Fatt.Forn.",
                        wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE,wx.ART_TOOLBAR,(16,16)))

        tb.Bind(wx.EVT_TOOL, self._registra_fatt_forn_handler, id=ID_REG_FATT_FORN)
        tb.realize()
        #return DocumentoBasePanel._configure_documento_toolbar(self)

        #self.listino=None
        #self.__do_layout()
        #self._fill_combobox()        
        #self._reset_page_state()        
        #self._bind()
        #self.update_fields()
    
#    def _init_toolbar(self):
#        self._toolbar.add_label_tool(ID_REG_FATT_FORN, 'Reg. Fatt. Forn', wx.ART_NORMAL_FILE)
#        self._toolbar.realize()
#        self._toolbar.Bind(wx.EVT_TOOL, self._on_registra_fatt_forn,id=ID_REG_FATT_FORN)
    
    def _layout(self):
        boxsizer = wx.BoxSizer(wx.VERTICAL)
        
        #self._init_toolbar()
        boxsizer.Add(self._toolbar,0,wx.EXPAND)
        
        boxsizer.Add(wx.StaticLine(self),1,wx.EXPAND)
        
        orsizer=wx.BoxSizer()
        
        orsizer.Add(self.numero,0,wx.ALL,border=mDefaultBorder)
        
        orsizer.AddSpacer(10)        
        
        self.intestatario.set_label('Fornitore')
        self.intestatario.set_lookup_context(lookup.LOOKUP_FORNITORI)
        orsizer.Add(self.intestatario,0,wx.ALL,border=mDefaultBorder)
        orsizer.AddSpacer(10)
                
        self.data.set_label('Data Arrivo')
        orsizer.Add(self.data,0,wx.ALL,border=mDefaultBorder)
        
        orsizer.AddSpacer((400,1))
        self.listino.hide()
        #self.listino.set_tipo(co.LISTINO_ACQUISTO)
        #orsizer.Add(self.listino,0,wx.ALL,border=mDefaultBorder)
        
        boxsizer.Add(orsizer)        

        boxsizer.Add(self.notebook,0,wx.EXPAND,border=mDefaultBorder)
        
        orsizer=wx.BoxSizer()
        
        orsizer.Add(self.spese,0,wx.TOP|wx.EXPAND,border=mDefaultBorder)
        
        orsizer.AddStretchSpacer(2)
        
        orsizer.Add(self.get_totali_ctrl(),0,wx.TOP|wx.EXPAND|wx.GROW|wx.ALIGN_RIGHT,border=mDefaultBorder)
        
        boxsizer.Add(orsizer,0,wx.TOP|wx.EXPAND,border=mDefaultBorder)
        self.SetSizer(boxsizer)
                
        #self.SetClientSize(self.notebook.GetClientSize())
        self.Layout()
    
    def _on_intestatario_selected(self,intestatario):
        print '_on_fornitore_selected'
        #self.listino.set_string_selection(intestatario.listino.codice)
        #self.dettaglio_doc_panel.prodotto.set_filter(intestatario)                
        #self.dettaglio_doc_panel.prodotto.enable(True)
        #self.dettaglio_doc_panel.iva_ctrl.set_string_selection(intestatario.iva.codice)
    
#    def _is_valid(self):#TODO:
#        righe_cont=self.dettaglio_doc_panel.get_righe_count()
#        if not righe_cont>0:
#            wx.GetApp().show_message("Impossibile procedere: nessuna riga in dettaglio.")
#            return False
#        return True

    def _get_dettaglio_panel_class(self):
        return DettaglioArrivoMerceSPanel
        
    def update_fields(self,obj):
        print self.__class__.__name__,'.update_fields'
        if obj is None:
            return
        DocumentoPanel.update_fields(self, obj)
        self.get_toolbar().EnableTool(ID_REG_FATT_FORN,not obj.is_chiuso())
        #self.dettaglio_doc_panel.prodotto.set_filter(self.intestatario.get_value())

    def update_object(self,obj):
        print self.__class__.__name__,'.update_object'
        DocumentoPanel.update_object(self,obj)
            
    def _registra_fatt_forn_handler(self,evt):
        print 'eccomi'


#===============================================================================
# RegFattFornPanel
#===============================================================================
class RegFattFornPanel(DocumentoBasePanel):
    TITLE='Registrazione Fattura Fornitore'
    def __init__(self,*args,**kwargs):
        DocumentoBasePanel.__init__(self,*args,**kwargs)
        self.data_fatt_forn = co.KDateCtrl(self,label='Data Fatt. Forn',orientation=wx.VERTICAL)
        self.numero_fatt_forn = co.LabelTextCtrl(parent=self,label='Fatt. Forn',size=(85,-1),orientation=wx.VERTICAL)
        self._layout()
        #self._fill_combobox()        
        #self._reset_page_state()        
        #self._bind()
        #self.update_fields()
#    def _init_toolbar(self):
#        self._toolbar.RemoveTool(wx.ID_PRINT)
#        self._toolbar.realize()
    
    def _layout(self):
        boxsizer = wx.BoxSizer(wx.VERTICAL)
        
        #self._init_toolbar()
        boxsizer.Add(self._toolbar,0,wx.EXPAND)
        
        boxsizer.Add(wx.StaticLine(self),1,wx.EXPAND)
        
        orsizer=wx.BoxSizer()
        
        orsizer.Add(self.numero,0,wx.ALL,border=mDefaultBorder)
        
        orsizer.AddSpacer(10)        
        
        self.intestatario.set_label('Fornitore')
        self.intestatario.set_lookup_context(lookup.LOOKUP_FORNITORI)
        orsizer.Add(self.intestatario,0,wx.ALL,border=mDefaultBorder)
        orsizer.AddSpacer(10)
                
        self.data.set_label('Data Reg.')
        orsizer.Add(self.data,0,wx.ALL,border=mDefaultBorder)
        
        orsizer.AddSpacer((130,1))
        #self.listino.set_tipo(co.LISTINO_ACQUISTO)
        #orsizer.Add(self.listino,0,wx.ALL,border=mDefaultBorder)
        
        orsizer.AddSpacer(10)
         
        orsizer.Add(self.numero_fatt_forn,0,wx.ALL,border=mDefaultBorder)
        
        orsizer.Add(self.data_fatt_forn,0,wx.ALL,border=mDefaultBorder)
        
        
        boxsizer.Add(orsizer)        

        boxsizer.Add(self.notebook,0,wx.EXPAND,border=mDefaultBorder)
        
        orsizer=wx.BoxSizer()
        
        #orsizer.Add(self.spese,0,wx.TOP|wx.EXPAND,border=mDefaultBorder)
        orsizer.AddSpacer((100,10))
        orsizer.AddStretchSpacer(1)
        
        orsizer.Add(self.get_totali_ctrl(),0,wx.TOP|wx.EXPAND|wx.GROW|wx.ALIGN_RIGHT,border=mDefaultBorder)
        
        boxsizer.Add(orsizer,0,wx.TOP|wx.EXPAND,border=mDefaultBorder)
        self.SetSizer(boxsizer)
        boxsizer.Layout()
        
    
    def _get_dettaglio_panel_class(self):
        return DettaglioRegFattFornSPanel
        
    def update_fields(self,obj):
        print self.__class__.__name__,'.update_fields'
        if obj is None:
            return
        self.data_fatt_forn.set_value(obj.get_data_fatt_forn())
        self.numero_fatt_forn.set_value(obj.get_numero_fatt_forn_fmt())
        DocumentoBasePanel.update_fields(self, obj)
        #self.dettaglio_doc_panel.prodotto.set_filter(self.intestatario.get_value())

    def update_object(self,obj):
        print self.__class__.__name__,'.update_object'        
        obj.data_fatt_forn=self.data_fatt_forn.get_value()
        obj.set_numero_fatt_forn(self.numero_fatt_forn.get_value())
        DocumentoBasePanel.update_object(self,obj)
        
        
#===============================================================================
# DocumentiOptionPanel
#===============================================================================
class DocumentiOptionPanel(OpzioniPanelBase):
    NAME='Documenti'
    def __init__(self,*args,**kwargs):
        OpzioniPanelBase.__init__(self,*args,**kwargs)
        self.__do_layout()
        self._bind()
           
    def __do_layout(self):
        mainsizer=wx.BoxSizer(wx.VERTICAL)
        fieldsizer = wx.GridBagSizer(0,0)
        
        boxsizer=wx.BoxSizer(wx.VERTICAL)        
        boxsizer.AddSpacer(10)
        titolo=wx.StaticText(self,label="Vendite al Banco")
        font=titolo.GetFont()
        font.SetWeight(wx.FONTWEIGHT_BOLD)
        titolo.SetFont(font)
        boxsizer.Add(titolo,0,wx.ALL,border=mDefaultBorder)
        boxsizer.AddSpacer(5)
        
        self.listino_vendita_banco = co.ListinoCtrl(self)
        boxsizer.Add(self.listino_vendita_banco,0,wx.ALL,border=mDefaultBorder)
        
#        self.iva_default = co.ComboBox(id=wx.NewId(),parent=self,size=wx.Size(197, 25),style=wx.CB_READONLY,item_info='codice')
#        boxsizer.Add(co.CompositeCtrl(self.iva_default,label='Iva di default'),0,wx.ALL,border=mDefaultBorder)
        #boxsizer.Add(self.gestione_magazzino,0,wx.TOP|wx.RIGHT,border=mDefaultBorder)
        
        boxsizer.AddSpacer(20)
        
        titolo=wx.StaticText(self,label="Fatture")
        font=titolo.GetFont()
        font.SetWeight(wx.FONTWEIGHT_BOLD)
        titolo.SetFont(font)
        boxsizer.Add(titolo,0,wx.ALL,border=mDefaultBorder)
        boxsizer.AddSpacer(5)
        
        self.numerazione_auto = wx.CheckBox(parent=self,label="Numerazione automatica",style=wx.ALIGN_RIGHT)
        boxsizer.Add(self.numerazione_auto,0,wx.TOP|wx.RIGHT,border=mDefaultBorder)
        
        self.next_num_fattura=co.LabelTextCtrl(self,size=(60,-1),label='Prossimo numero fattura')
        boxsizer.Add(self.next_num_fattura,0,wx.ALL,border=mDefaultBorder)
        
        self.elimina_fatture = wx.CheckBox(parent=self,label="Abilita eliminazione fatture",style=wx.ALIGN_RIGHT)
        boxsizer.Add(self.elimina_fatture,0,wx.TOP|wx.RIGHT,border=mDefaultBorder)
                
        fieldsizer.Add(boxsizer,(0,0),flag=wx.ALL|wx.EXPAND ,border=0)#riga zero colonna 1                
        fieldsizer.AddGrowableRow(0)
        fieldsizer.AddGrowableCol(1)
        
        mainsizer.Add(fieldsizer,1,flag=wx.ALL|wx.EXPAND ,border=10)#riga zero colonna 1        
        
        mainsizer.Layout()
        self.SetAutoLayout(True)
    
    def _bind(self):
        self.Bind(wx.EVT_CHECKBOX, self.aggiorna_num_auto,id=self.numerazione_auto.Id)
    
#    def _request_listini(self):
#        '''Fa una richiesta al database.''' 
#        observer=wx.GetApp().get_observer()
#        observer.set_context('LISTINI')                
#        objects=observer.get_objects()
#        return objects
    
    def _request_next_fatt(self):
        observer=wx.GetApp().get_observer()
        observer.set_context('FATTURE')
        num=observer.action_request('get_next_num')
        return num
    
    def _update_next_fatt(self):
        observer=wx.GetApp().get_observer()
        observer.set_context('FATTURE')
        observer.action_request('set_next_num',self.next_num_fattura.get_value())
    
    def aggiorna_num_auto(self,evt=None):
        if self.numerazione_auto.GetValue():
            self.next_num_fattura.set_value(self._request_next_fatt())
            self.next_num_fattura.enable(True)
        else:
            self.next_num_fattura.clear()
            self.next_num_fattura.enable(False)
    
    def update_fields(self,opzioni):
        print 'Generale.update_fields'
        self.listino_vendita_banco.set_string_selection(opzioni.LISTINO_VENDITA_BANCO_NAME)
        self.numerazione_auto.SetValue(to_bool(opzioni.FATT_NUM_AUTO))
        self.elimina_fatture.SetValue(to_bool(opzioni.ELIMINA_FATTURE))
        self.aggiorna_num_auto()        
    
    def reset_fields(self):
        print 'DocumentiOptionPanel.reset_fields'
        #self.gestione_magazzino.SetValue(False)
    
    def update_object(self,opzioni):
        print 'Generale.update_object'
        opzioni.LISTINO_VENDITA_BANCO_NAME=self.listino_vendita_banco.get_string_selection()
        opzioni.LISTINO_VENDITA_BANCO=self.listino_vendita_banco.get_selected_object()
        opzioni.FATT_NUM_AUTO=to_string(self.numerazione_auto.GetValue())
        opzioni.ELIMINA_FATTURE=to_string(self.elimina_fatture.GetValue())
        if self.numerazione_auto.GetValue():
            self._update_next_fatt()
    
    def before_close(self,observer):
        pass


#===============================================================================
# DocumentoEditor
#===============================================================================
class DocumentoEditor(dialogs.KoroObjectEditor):
    def __init__(self,parent):
        dialogs.KoroObjectEditor.__init__(self,parent)
    
    def set_panel(self,panel):
        super(DocumentoEditor,self).set_panel(panel)
        self.bind_toolbar(wx.EVT_TOOL, self._close_handler, id=wx.ID_CLOSE)
    
    def _close_handler(self,evt):
        '''Imposta il codice da processare in base alla richiesta fatta dall'object_viewer. I valori possono essere:
        * wx.ID_SAVE per salvare l'oggetto,
        * wx.ID_DELETE per non salvare l'oggetto.'''
        code=wx.ID_SAVE
        if self._object.is_pending_object():
            response=wx.GetApp().show_question('Salvare il documento appena creato?')
            if response==wx.ID_CANCEL:
                evt.Skip(False)
                return
            if response==wx.ID_NO:
                code=wx.ID_DELETE
            elif response!=wx.ID_YES:
                raise#TODO:....che succede qui non deve verificarsi mai
        try:
            self._process_code(code)
            self.end_modal(code)
        except Exception,inst:#TODO:qui catturo tutto...catturare solo l'eccezione che di save_object
            print self.__class__.__name__,'_close_handler: {0}'.format(inst)
    
    def _process_code(self,code):
        if code==wx.ID_SAVE:
            self._save_object()
        elif code==wx.ID_DELETE:
            self._delete_object()
    
    def _save_object(self):
        print self.__class__.__name__,'_save_object'
        wx.BeginBusyCursor()
        try:
            self.update_object()
            observer=self.Parent._get_page_observer()
            observer.save_object(self._object)
            self._after_save_object()
        except Exception,err:
            print err
            raise exception.KoroDBOperationException('operation exception')
        finally:
            wx.EndBusyCursor()
    
    def _delete_object(self):
        observer=self.Parent._get_page_observer()
        observer.delete_object(self._object)
        self._after_delete_object()
        self.set_object(None)
    
    def _after_save_object(self):
        pass
    
    def _after_delete_object(self):
        pass
    
    def show(self,obj):
        return super(DocumentoEditor,self).show(obj)
    
#    def show(self,obj):
#        if self._chiedi_intestatario(obj):
#            return super(DocumentoEditor,self).show(obj)
    
#    def _chiedi_intestatario(self,obj):#TODO: eliminare! spostato in DocumentoListPage
#        if (not obj.is_pending_object() or 
#            obj.is_cascading_object()):
#            return True
#        dlg=self._get_lookup_intestatario()
#        action=dlg.show()
#        if action==wx.ID_CANCEL:
#            dlg.Destroy()
#            return False
#        intestatario=dlg.get_selection()
#        dlg.Destroy()
#        obj.set_intestatario(intestatario)
#        return True
    
    def _get_lookup_intestatario(self):
        pass


#===============================================================================
# ArrivoMerceEditor
#===============================================================================
class ArrivoMerceEditor(DocumentoEditor):
    def __init__(self,*args,**kwargs):
        DocumentoEditor.__init__(self,*args,**kwargs)
        self.set_panel(ArrivoMercePanel(self))
        self.bind_toolbar(wx.EVT_TOOL, self._registra_fatt_handler, id=ID_REG_FATT_FORN)
    
    def _registra_fatt_handler(self,evt):
        if self._object.is_chiuso():
            wx.GetApp().show_message('Fattura Fornitore già registrata.')
            return
        response=wx.GetApp().show_question('Creare il documento a partire da quello corrente?')
        if response==wx.ID_NO:
            return
        wx.BeginBusyCursor()
        try:
            self._process_code(wx.ID_SAVE)
            observer=wx.GetApp().get_observer()
            observer.set_context('REG_FATT_FORN')            
            #doc=observer.request_action('REG_FATT_FORN',"genera_reg_fatt_forn",obj)
            doc=observer.genera_reg_fatt_forn(self._object)
            doc.cascading = True
            self.end_modal(ID_REG_FATT_FORN)
            #posso chiamare la funzione in CallAfter perché devono ancora concludersi
            # gli eventi del click su 'Nuovo' o su 'Visualizza', quindi viene eseguito
            #prima self.end_modal e poi self.Parent_mostra_documento
            wx.CallAfter(self.Parent.mostra_documento,doc)
            #save=self._processa_documento(doc)
            #if save:
                #observer.set_context('ARRIVI_MERCE')
                #observer.request_action('ARRIVI_MERCE',"chiudi",obj,doc)
                #self.update()
            #observer.request_action('ARRIVI_MERCE',"chiudi",self._object,doc)            
        except Exception,err:
            print err
            wx.GetApp().show_error("Si e' verificato un errore: {0}".format(err))
            if wx.IsBusy():
                wx.EndBusyCursor()
        finally:
            pass
    
#    def _get_lookup_intestatario(self):
#        return lookup.LOOKUP_FORNITORI(wx.GetApp().GetTopWindow(),filter=None)
        

#===============================================================================
# FatturaEditor
#===============================================================================
class FatturaEditor(DocumentoEditor):
    def __init__(self,*args,**kwargs):
        DocumentoEditor.__init__(self,*args,**kwargs)
        self.set_panel(FatturaPanel(self))
    
#    def _get_lookup_intestatario(self):
#        return lookup.LOOKUP_CLIENTI(wx.GetApp().GetTopWindow(),filter=None)


class PreventivoEditor(DocumentoEditor):
    def __init__(self,*args,**kwargs):
        DocumentoEditor.__init__(self,*args,**kwargs)
        self.set_panel(PreventivoPanel(self))
    
#    def _get_lookup_intestatario(self):
#        return lookup.LOOKUP_CLIENTI(wx.GetApp().GetTopWindow(),filter=None)

#===============================================================================
# RegFattFornEditor
#===============================================================================
class RegFattFornEditor(DocumentoEditor):
    def __init__(self,*args,**kwargs):
        DocumentoEditor.__init__(self,*args,**kwargs)
        self.set_panel(RegFattFornPanel(self))
    
    def _after_save_object(self):
        if not hasattr(self._object, 'padre'):
            return
        observer=wx.GetApp().get_observer()
        observer.set_context('ARRIVI_MERCE')
        observer.chiudi(self._object.padre,self._object)
    
    def _after_delete_object(self):
        observer=wx.GetApp().get_observer()
        observer.set_context('ARRIVI_MERCE')
        observer.annulla_chiusura(self._object)
    
#    def _get_lookup_intestatario(self):
#        return lookup.LOOKUP_FORNITORI(wx.GetApp().GetTopWindow(),filter=None)


#===============================================================================
# EditorManager
#===============================================================================
class EditorManager(object):
    def __init__(self,parent):
        self._parent=parent
    
    def edit(self,obj):
        editor=_get_editor(obj)(self._parent)
        retcode=editor.show(obj)
        obj=editor.get_object()
        return obj
    